package server.interfaces;

import java.util.Vector;

import server.AgentIDException;

import agent.IAgentProxy;

import com.Event;
import com.sun.spot.util.IEEEAddress;
import com.sun.squawk.Isolate;

/**
 * IMobileAgentExecutionEngine is the interface implemented by the key-class of the whole architecture.
 * It knows every component of the architecture and manages all their interactions and every component knows it to make requests.
 * @author Francesco Aiello, Antonio Guerrieri, Raffaele Gravina
 *
 */
public interface IMobileAgentExecutionEngine {
	
	/**
	 * sends events to other mobile agents, (local or remotes).
	 * It must be possible send "Broadcast" messages. 
	 * @param sourceMA source Mobile Agent
	 * @param targetMA target Mobile Agent
	 * @param message message to send
	 * @param local needs to specify if it's a local or remote communication
	 */
	public  void send(String sourceMA, String targetMA, Event message, boolean local);
	
	/**
	 * creates a new agent in the local node or in a remote node. 
	 * @param agentID ID of the agent to create
	 * @param sourceMA source Mobile Agent
	 * @param agent name of the agent's class
	 * @param params parameters for the agent creation
	 * @param nodeID ID of the node where the mobile agent must be created
	 * @return true if the operation was successful, false otherwise
	 */
	public 	boolean create(String agentID, String sourceMA, String agent, String [] params, String nodeID);

	/**
	 * The difference with "create(String agentID, String sourceMA, String agent, String [] params, String nodeID)"
	 * is that here is not possible to specify the ID of the agent
	 * @param sourceMA source Mobile Agent
	 * @param agent name of the agent's class
	 * @param params parameters for the agent creation
	 * @param nodeID ID of the node where the mobile agent must be created
	 * @return true if the operation was successful, false otherwise
	 */
	public 	boolean create(String sourceMA, String agent, String [] params, String nodeID);
	
	/**
	 * Clones an agent locally or remotely.
	 * @param sourceMA source Mobile Agent
	 * @param maID ID of the cloned Mobile Agent
	 * @param nodeID ID of the node where the mobile agent must be cloned
	 */
	public  void clone(String sourceMA, String maID, String nodeID);
	
	/**
	 * Sends a migration request to the migration manager
	 * @param sourceMA Mobile Agent ID that wants to migrate
	 * @param nodeID ID of the node where the mobile agent wants to migrate 
	 */
	public  void migrate(String sourceMA, String nodeID);
	
	/**
	 * Sends a sensing request to the sensorBoard managers
	 * @param sourceMA Mobile Agent ID that wants to access to a resource
	 * @param backEvent event with sensing information
	 */
	public  void sense(String sourceMA, Event backEvent);
	
	/**
	 * Sends a actuating request to the sensorBoard managers
	 * @param sourceMA Mobile Agent ID that wants to actuate something
	 * @param params parameters with info about the actuating
	 */
	public  void actuate(String sourceMA, Event params);
	
	/**
	 * Sends a Input request to the sensorBoard manager
	 * @param sourceMA Mobile Agent ID that wants to access to the input resource
	 * @param backEvent event with IO information
	 */
	public 	void input (String sourceMA, Event backEvent);
	
	/**
	 * Sends a flash request to the sensorBoard manager
	 * @param sourceMA Mobile Agent ID that wants to access to the IO resource
	 * @param backEvent event with IO information
	 */
	public 	void flash (String sourceMA, Event backEvent);
	
	/**
	 * Sends a setting timer request to the timerManager
	 * @param sourceMA Mobile Agent ID that wants to set timer
	 * @param periodic Specifies if the timer is periodic or is one-shot
	 * @param timeout timeout's length
	 * @param backEvent event to send at expiration time
	 * @return ID of the created timer
	 */
	public  String setTimer(String sourceMA, boolean periodic, long timeout, Event backEvent);
	
	/**
	 * Sends a resetting timer request to the timerManager. It terminates the timer
	 * @param sourceMA Mobile Agent ID that wants to set timer 
	 * @param timerID ID of the timer to terminate
	 */
	public  void resetTimer(String sourceMA, String timerID);
	
	/**
	 * Gets every local mobile agent.  
	 * 
	 * @return Returns local agents.
	 */
	public  Vector getMobileAgents();
		
	/**
	 * Gets the IDs of every local mobile agent.  
	 * 
	 * @return Returns the ID of the local agents.
	 */
	public 	Vector getLocalAgentsID();
	
	/**
	 * Gets the IDs of the neighbour nodes
	 * @return IDs of the neighbour nodes
	 */
	public  Vector getNeighbors();
	
	/**
	 * Gets the IDs of the remote mobile agent on the neighbour nodes
	 * @return IDs of the remote mobile agent
	 */
	public 	Vector getRemoteAgentsID();
	
	/**
	 * Adds a new node in the set of neighbour nodes
	 * @param address address of the node
	 * @param agent node's agents
	 */
	public 	void addNeighbor(String address, Vector agent);
	
	/**
	 * Adds a new node in the set of local agents
	 * @param agent
	 */
	public 	void addAgent(Isolate agent);	
	
	/**
	 * Generates a random suffix for an agent's ID 
	 * @return an alpha-numeric string
	 */
	public String generateAgentSuffix ();
	
	/**
	 * Generates a unique string for the agent's ID, the last 8 chars of the MAC address, plus a suffix that
	 * can be generated randomly by generateAgentSuffix()
	 * @param agentSuffix an agent suffix
	 * @return the agent ID
	 * @throws AgentIDException throws if the suffix contains an disallowed char 
	 */
	public  String generateAgentID(String agentSuffix) throws AgentIDException;
	
	/**
	 * Returns the IEEEAddress of the node
	 * 
	 * @return the IEEEAddress of the node.
	 */
	public 	IEEEAddress getMyIEEEAddress();
	
	/**
	 * Sends a starting event to the agent
	 * @param agentName ID of the agent
	 */
	public 	void startAgent (String agentName);
	
	/**
	 * Sends a terminating event to the agent
	 * @param agent ID of the agent
	 */
	public 	void terminateAgent (String agent);
	
	/**
	 * Getter of the IMobileAgentMigrationManager component
	 * 
	 * @return Returns the migration manager component.
	 */
	public IMobileAgentMigrationManager 	getMigrationManger ();
	
	/**
	 * Getter of the IMobileAgentCommunicationChannelSender component
	 * 
	 * @return Returns the migration manager component.
	 */
	public IMobileAgentCommunicationChannelSender getCommunicationChannel();
	
	/**
	 * Gets the agent's Isolate object  
	 * @param agentID ID of the agent
	 * @return the agent's Isolate object
	 */
	public Isolate getAgent(String agentID);

	/**
	 * Gets the agent's proxy 
	 * @param agentID agent's ID
	 * @return the agent's proxy 
	 */
	public IAgentProxy getAgentProxy(String agentID);
	
	/**
	 * Sends a migration executed event to an agent
	 * @param agentID agent's ID
	 */
	public void migrationExecuted(String agentID);
	
	/**
	 * Removes an agent from the set of local agents 
	 * @param agent agent's ID
	 * @return true if the operation was successful, false otherwise
	 */
	public boolean removeAgent(String agent);
	
	/**
	 * Removes an agent's proxy 
	 * @param agentID agent's ID
	 */
	public void removeAgentProxy(String agentID);
	
	/**
	 * Getter of the execution engine name 
	 * @return Returns the execution engine name.
	 */
	public String getExecutionEngineName();
}
